package com.simple.relaxed.anno.impl;

import com.simple.relaxed.anno.Inject;
import com.simple.relaxed.manager.impl.InjectManager;

import java.lang.reflect.Field;
import java.util.Map;

public class InjectImpl {

    /**
     * 将InjectManager中管理的对象，互相注入被Inject注解标记的Filed
     */
    public static void inject() {
        Map<String, Object> lookup = InjectManager.getInstance().lookup();
        for (Map.Entry<String, Object> entry : lookup.entrySet()) {
            Object value = entry.getValue();
            Class<?> aClass = value.getClass();
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                Inject inject = field.getDeclaredAnnotation(Inject.class);
                if (inject == null) {
                    continue;
                }
                field.setAccessible(true);
                String bindName = inject.bindName();
                try {
                    if (bindName.isEmpty()) {
                        Class<?> type = field.getType();
                        String name = type.getName();
                        Object o = lookup.get(name);
                        if (o == null) {
                            for (Object obj : lookup.values()) {
                                if (type.isInstance(obj)) {
                                    o = obj;
                                    break;
                                }
                            }
                        }
                        field.set(value, o);
                    } else {
                        Object o = lookup.get(bindName);
                        field.set(value, o);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 向指定的对象中所有被Inject注解标记的Filed，注入被InjectManager管理的对象
     *
     * @param object 被注入的对象
     */
    public static void inject(Object object) {
        Class<?> aClass = object.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            Inject inject = field.getDeclaredAnnotation(Inject.class);
            if (inject == null) {
                continue;
            }
            field.setAccessible(true);
            String bindName = inject.bindName();
            try {
                if (bindName.isEmpty()) {
                    Class<?> type = field.getType();
                    Object lookup = InjectManager.getInstance().lookup(type.getName());
                    if (lookup == null) {
                        for (Object o : InjectManager.getInstance().lookup().values()) {
                            if (type.isInstance(o)) {
                                lookup = o;
                                break;
                            }
                        }
                    }
                    field.set(object, lookup);
                } else {
                    field.set(object, InjectManager.getInstance().lookup(bindName));
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
